var SkyRTC;
SkyRTC = function () {

    var PeerConnection = (window.RTCPeerConnection || window.PeerConnection || window.webkitPeerConnection00 || window.webkitRTCPeerConnection || window.mozRTCPeerConnection);
    var URL = (window.URL || window.webkitURL || window.msURL || window.oURL);
    var getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia);

    var nativeRTCIceCandidate = (window.mozRTCIceCandidate || window.RTCIceCandidate);
    var nativeRTCSessionDescription = (window.mozRTCSessionDescription || window.RTCSessionDescription); // order is very important: "RTCSessionDescription" defined in Nighly but useless
    var moz = !!navigator.mozGetUserMedia;

/*
    var iceServer = {
        "iceServers": [
            {
                "urls": [
                    "stun:webrtc.qq-kan.com:3478"
                ]
            }, {
								"urls" : ["turn:webrtc.qq-kan.com?transport=udp"],
								"username" : "qq-kan",
								"credential" : "1544115907",
                "credentialType": "password"
          }      
        ],
      //"iceTransportPolicy": "relay"
    };
*/
		var iceServer={"iceServers":[{"urls":["turn:webrtc.qq-kan.com?transport=udp"],"username":"qq-kan","credential":"1544115907"}],
			             "iceTransportPolicy":"all",
			             "iceCandidatePoolSize":"0"};
    var packetSize = 1000;

 function NewgetUserMedia(constrains,success,error){//访问用户媒体设备的兼容方法
	  if(navigator.mediaDevices.getUserMedia){//最新标准API
	   navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error);
	  } else if (navigator.webkitGetUserMedia){//webkit内核浏览器
	   navigator.webkitGetUserMedia(constrains).then(success).catch(error);
	  } else if (navigator.mozGetUserMedia){//Firefox浏览器
	   navagator.mozGetUserMedia(constrains).then(success).catch(error);
	  } else if (navigator.getUserMedia){//旧版API
	   navigator.getUserMedia(constrains).then(success).catch(error);
	  }
 }


    /**********************************************************/
    /*                                                        */
    /*                       事件处理器                       */
    /*                                                        */

    /**********************************************************/
    function EventEmitter() {
        this.events = {};
    }

    //绑定事件函数
    EventEmitter.prototype.on = function (eventName, callback) {
        this.events[eventName] = this.events[eventName] || [];
        this.events[eventName].push(callback);
    };
    //触发事件函数
    EventEmitter.prototype.emit = function (eventName, _) {
        var events = this.events[eventName],
            args = Array.prototype.slice.call(arguments, 1),
            i, m;

        if (!events) {
            return;
        }
        for (i = 0, m = events.length; i < m; i++) {
            events[i].apply(null, args);
        }
    };


    /**********************************************************/
    /*                                                        */
    /*                   流及信道建立部分                     */
    /*                                                        */

    /**********************************************************/


    /*******************基础部分*********************/
    function skyrtc() {

        this.connectmode = null;
        this.connectsource = null;
        this.sessionId = null;
        //本地media stream
        this.localMediaStream = null;
        this.remoteMediaStream = null;
        this.speak =null;
        this.mute =null;
        this.reconnect =null;
        this.connected =null;
        //所在房间
        this.room = "";
        //接收文件时用于暂存接收文件
        this.fileData = {};
        //本地WebSocket连接
        this.socket = null;
        //本地socket的id，由后台服务器创建
        this.me = null;
        this.peer = null;
        //保存所有与本地相连的peer connection， 键为socket id，值为PeerConnection类型
        this.peerConnections = {};
        //保存所有与本地连接的socket的id
        this.connections = [];
        //初始时需要构建链接的数目
        this.numStreams = 0;
        //初始时已经连接的数目
        this.initializedStreams = 0;
        //保存所有的data channel，键为socket id，值通过PeerConnection实例的createChannel创建
        this.dataChannels = {};
        //保存所有发文件的data channel及其发文件状态
        this.fileChannels = {};
        //保存所有接受到的文件
        this.receiveFiles = {};
        this.remotesdp = null;
        this.messagecallback = null;
       
        this.IceCandidate = new Array();
        this.mediaRecorder = null;
        this.IceComplete = null;
        this.Recorded = null;
    }

    //继承自事件处理器，提供绑定事件和触发事件的功能
    skyrtc.prototype = new EventEmitter();


    /*************************服务器连接部分***************************/


    //本地连接信道，信道为websocket
    skyrtc.prototype.connect = function (server,meid, peerid,conmode,consource) {
        console.log("skyrtc  connect  server = ", server);
        var socket, that = this;
        this.IceComplete = false;
        this.connected =false;
        this.speak =true;
        this.mute =true;
        this.IceComplete = false;
        this.Recorded = false;
        this.reconnect= false;
        this.connectmode = conmode;
        this.connectsource = consource;
        this.sessionId = this.uuid();
        meid = meid || "";
        socket = this.socket = new WebSocket(server);
        socket.onopen = function () {
            console.log("skyrtc  WebSocket open ", server);
            socket.send(JSON.stringify({
                "eventName": "__connectto",
                "data": {
                    "sessionId": that.sessionId,
                    "sessionType": "IE",
                    "messageId": that.uuid(),
                    "from": meid,
                    "to": peerid
                }
            }));
						that.connected = true;
            that.emit("socket_opened", socket);
        };

        socket.onmessage = function (message) {
           // console.log("onmessage  recv  = ", message);
            var json = JSON.parse(message.data);
            if (json.eventName) {
                that.emit(json.eventName, json.data);
            } else {
                that.emit("socket_receive_message", socket, json);
            }
        };

        socket.onerror = function (error) {
        	  that.reconnect= true;
        	  that.connected =false;
            console.log("skyrtc  WebSocket onerror ",error);
            that.emit("socket_error", error, socket);
        };

        socket.onclose = function (data) {
	       console.log("skyrtc  WebSocket onclose",data);
            if (that.localMediaStream !== null) {
                //    that.localMediaStream.close();
                that.localMediaStream = null;
            }
           if (that.remoteMediaStream !== null) {
           	  that.remoteMediaStream = null;
           }
            var pcs = that.peerConnections;
            for (i = pcs.length; i--;) {
                that.closePeerConnection(pcs[i]);
            }
            that.peerConnections = [];
            that.dataChannels = {};
            that.fileChannels = {};
            that.connections = [];
            that.fileData = {};
            that.speak =null;
            that.mute =null;
            that.IceComplete = null;
		        that.Recorded = null;
		        that.reconnect= null;
		        that.connected =false;
            that.emit('socket_closed', socket);
            
        };

        this.on('_session_disconnected', function (data) {
            console.log("WebSocket _session_disconnected", data);
            that.closePeerConnection(that.peerConnections[0]);
            delete that.peerConnections[0];
            delete that.dataChannels[0];

        });


        this.on('_create', function (data) {

            console.log("WebSocket _create", data);
            //获取所有服务器上的
            if (data.state === "online") {
                that.connections = [0];
                that.peer = data.to;
                that.me = data.from;
                that.emit("get_peers", that.connections);
                that.emit('connected', socket);
            } else {

                that.emit('no_online', socket);
            }

        });

      

        this.on('_new_peer', function (data) {
            that.connections.push(data.socketId);
            var pc = that.createPeerConnection(data.socketId);
					   that.localMediaStream.getTracks().forEach(function(track) {
					    pc.addTrack(track, that.localMediaStream);
					  });
            that.emit('new_peer', data.socketId);
        });

        this.on('_remove_peer', function (data) {
            var sendId;
            that.closePeerConnection(that.peerConnections[data.socketId]);
            delete that.peerConnections[data.socketId];
            delete that.dataChannels[data.socketId];
            for (sendId in that.fileChannels[data.socketId]) {
                that.emit("send_file_error", new Error("Connection has been closed"), data.socketId, sendId, that.fileChannels[data.socketId][sendId].file);
            }
            delete that.fileChannels[data.socketId];
            that.emit("remove_peer", data.socketId);
        });

        this.on('_offer', function (data) {
            that.receiveOffer(data.socketId, data.sdp);
            that.emit("get_offer", data);
        });

        this.on('_answer', function (data) {
        	  
           if (data.state === "successed") {
                	console.log("WebSocket recive receiveAnswer", data.sdp);
            			that.receiveAnswer(0, data.sdp);
                  that.emit('get_answer', data);            		
            } else {
                console.log("WebSocket _answer failed", data);
            }

        });
        this.on("_ice_candidate", function (data) {    	
    	     	 console.log("WebSocket recive ice_candidate addIceCandidate ", data);  
            var obj =JSON.parse(data);
            var candidate = new nativeRTCIceCandidate({sdpMLineIndex:obj.sdpMLineIndex, candidate:obj.candidate});
            var peerc = that.peerConnections[0];	    
            peerc.addIceCandidate(candidate);
            that.emit('get_ice_candidate', candidate);
              
        });
        
         this.on('_post_message', function (data) {
         	  //console.log("WebSocket recive  _post_message result ", data); 
         	  var messageid =  data.messageId;
         	 
         	  if(that.messagecallback===undefined  || that.messagecallback===null){
         	  	  
         	    }else{
         	    typeof(that.messagecallback)==='function'&&that.messagecallback(data.message);
         	    that.messagecallback = null;
         	  }
            
           //that.emit('post_message', data.socketId);
        });
        
       this.on('_equipment_message', function (data) {
         	  var messageid =  data.messageId;      	             
            that.emit('equipment_message', data.message);
        });
        
        
        this.on('send_file_error', function (error, socketId, sendId, file) {
            that.cleanSendFile(sendId, socketId);
        });

        this.on('receive_file_error', function (error, sendId) {
            that.cleanReceiveFile(sendId);
        });

        this.on('ready', function () {
            console.log("ready    --------------------------------------");
            that.createPeerConnections();
            that.addStreams();
            that.sendOffers();
          
        });
    };

    skyrtc.prototype.postmessage = function (message,callback) {
    	if(this.connected==true && this.socket != null){   		  
    		    var messageid = this.uuid();
    		    this.messagecallback=callback;
            this.socket.send(JSON.stringify({
                "eventName": "__post_message",
                "data": {
                    "sessionType": "IE",
                    "messageId": messageid,
                    "from": this.me,
                    "to": this.peer,
                    "message": message
                }
            }));
            
    	}else{    		   
    	}
    };
    

    skyrtc.prototype.setlocalaudio = function (enable) {
    	if(this.initializedStreams>0){
    		    this.mute =enable;  
    		    if(this.localMediaStream!= null){
    		    	
    		    	      const tracks = this.localMediaStream.getAudioTracks();
                    for (i = 0, m = tracks.length; i < m; i++) {
                    tracks[i].enabled = this.mute;    
                     console.log("setlocalaudio", tracks[i]);    
                    } 
    		   	  
    		   	}
    	}else{
    		   
    	}
    };
    skyrtc.prototype.setlocalspeak = function (enable) {
    	
    	if(this.remoteMediaStream!=null){
                   this.speak = enable;    	 
    	 		    	   const tracks = this.remoteMediaStream.getAudioTracks();
                    for (i = 0, m = tracks.length; i < m; i++) {
                    tracks[i].enabled = this.speak; 
                    console.log("setlocalspeak", tracks[i]);    
                    }    		    
    	}else{
    		   
    	}
    };
    skyrtc.prototype.startrecord = function () {
    	var that = this;
    	if(this.remoteMediaStream!= null){    		 
    		  this.mediaRecorder = new MediaRecorder(this.remoteMediaStream);
    		  if(this.mediaRecorder!= null){  
    		   this.Recorded = true; 		  
    		  this.mediaRecorder.blobs = [];
    		  //var chunks = [],
    		  this.mediaRecorder.ondataavailable = function(e) {
                            that.mediaRecorder.blobs.push(e.data);
                            //chunks.push(e.data);
          };
          this.mediaRecorder.onstop = function (e) {
          	                if (that.mediaRecorder.blobs.length) {
                            recorderFile = new Blob(that.mediaRecorder.blobs, { 'type' : that.mediaRecorder.mimeType });
                           // chunks = [];
                            
								            var downloadUrl = window.URL.createObjectURL(recorderFile);								 
								            var link = document.createElement('a');
								            link.style.display = 'none';
								            link.href = downloadUrl;
								            link.download = 'media.webm';
								            link.disabled = false;
								            link.click();
								          }
         };
         this.mediaRecorder.start();
         
         }
    		
    	}
    	
    	
    };
    skyrtc.prototype.stoprecord = function () {
    	if(this.Recorded == true && this.remoteMediaStream!= null && this.mediaRecorder!= null){
    	   this.mediaRecorder.stop();	
    	   this.Recorded = false;
    	}
    	
    	
    };
    skyrtc.prototype.uuid = function () {
        var s = [];
        var hexDigits = "0123456789abcdef";
        for (var i = 0; i < 36; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }
        s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
        s[8] = s[13] = s[18] = s[23] = "-";
        var uuid = s.join("");
        return uuid;
    };

    /*************************流处理部分*******************************/


    //创建本地流
    skyrtc.prototype.createStream = function (options) {
        var that = this;
        that.createPeerConnection(0)
        options.video = !!options.video;
        options.audio = !!options.audio;

        if (getUserMedia) {
            this.numStreams++;
            getUserMedia.call(navigator, options, function (stream) {
                    that.localMediaStream = stream;
                    that.initializedStreams++;
           
                    console.log("initializedStreams", that.initializedStreams);
                    console.log("numStreams", that.numStreams);
                    that.emit("stream_created", stream);
                    if (that.initializedStreams === that.numStreams) {
                        that.emit("ready");
                    }
                },
                function (error) {
                    console.log("stream_create_error   11111-----");
                    that.emit("stream_create_error", error);
                });
        } else {
        	
          if(navigator.mediaDevices)
            {	
        	     navigator.mediaDevices.getUserMedia(options)
								    .then(function(mediaStream){
								    	    that.initializedStreams++;
								        console.log(mediaStream);
								        that.emit("stream_created", stream);
								        if (that.initializedStreams === that.numStreams) {
                        that.emit("ready");
                        }
								    })
								    .catch(function(error){
								        console.log(error);
								    });
       }else{
                console.log("navigator.mediaDevices  null ");
            }
            console.log("stream_create_error");
            that.emit("stream_create_error", new Error('WebRTC is not yet supported in this browser.'));
    
    
        }
    };

    //将本地流添加到所有的PeerConnection实例中
    skyrtc.prototype.addStreams = function () {
        var connection;
        var that = this;
        for (connection in this.peerConnections) {             
				    that.localMediaStream.getTracks().forEach(function(track) {
				         that.peerConnections[connection].addTrack(track, that.localMediaStream);
				    });
  
        }                    
    };
    skyrtc.prototype.InitStreamsAudio = function () {
    	 console.log("InitStreamsAudio-----------"); 
    	if(this.localMediaStream!= null){
    	 const tracks = this.localMediaStream.getAudioTracks();
       for (i = 0, m = tracks.length; i < m; i++) {
           tracks[i].enabled = this.mute;  
           console.log("InitStreamsAudio", tracks[i]);   
          
       } 
       for (i = 0, m = tracks.length; i < m; i++) {
       		if(tracks[i].enabled != this.mute){
       			 this.mute = tracks[i].enabled
       		}
      }
     }
    };
    skyrtc.prototype.InitStreamsAudioSpeak = function () {
    	 console.log("InitStreamsAudioSpeak-----------"); 
    	 if(this.remoteMediaStream!= null){    	 
	    	 const tracks = this.remoteMediaStream.getAudioTracks();
	       for (i = 0, m = tracks.length; i < m; i++) {
	           tracks[i].enabled = this.speak;
	           console.log("InitStreamsAudioSpeak", tracks[i]);  
	             
	       }
	       for (i = 0, m = tracks.length; i < m; i++) {
	           if(tracks[i].enabled != this.speak){
	           	  this.speak = tracks[i].enabled;
	           	}
	           
	             
	       }
     }
    };

    //将流绑定到video标签上用于输出
    skyrtc.prototype.attachStream = function (stream, domId) {

        var element = document.getElementById(domId);
        
        try 
        {
        	   element.srcObject = stream;
        } 
  		  catch (error) {
           var CompatibleURL = window.URL || window.webkitURL || window.mozURL;//可以通过URL.createObjectURL转换后设置为Video或Audio元素的src属性来使用
				   //element.src = CompatibleURL.createObjectURL(stream);   // 此处的代码将会报错  解决的办法是将video的srcObject属性指向stream即可
                    element.srcObject = stream;
                }
        
        this.InitStreamsAudioSpeak();
        this.InitStreamsAudio();
	      element.play();
    };

    /***********************信令交换部分*******************************/
    //向所有PeerConnection发送Offer类型信令
    skyrtc.prototype.sendOffers = function () {
		        console.log("sendOffers---------------------==================");
		        var i, m,
            pc,
            that = this,
            pcCreateOfferCbGen = function (pc, socketId) {
                return function (session_desc) {

             		pc.setLocalDescription(session_desc);
         
					       that.socket.send(JSON.stringify({
					            "eventName": "__offer",
					            "data": {
					                "sessionId": that.sessionId,
					                "sessionType": "IE",
					                "messageId": that.uuid(),
					                "to": that.peer,
					                "from": that.me,
					                "mode": that.connectmode,
					                "source": that.connectsource,
					                "sdp": session_desc.sdp
					            }
					        }));
                 console.log("local sdp---------------------==================",session_desc.sdp);

                };
            },
            pcCreateOfferErrorCb = function (error) {
                console.log(error);
            };

        for (i = 0, m = this.connections.length; i < m; i++) {
            pc = this.peerConnections[this.connections[i]];
            pc.createOffer(pcCreateOfferCbGen(pc, this.connections[i]), pcCreateOfferErrorCb);
        }

    };

    //接收到Offer类型信令后作为回应返回answer类型信令
    skyrtc.prototype.receiveOffer = function (socketId, sdp) {
        var pc = this.peerConnections[socketId];
        this.sendAnswer(socketId, sdp);
    };

    skyrtc.prototype.sendDisconnect = function (socketId) {
       
          var pc = this.peerConnections[socketId];
          this.socket.send(JSON.stringify({
                "eventName": "__disconnected",
                "data": {
                    "sessionId": this.sessionId,
		   							 "sessionType": "IE",
                    "messageId": this.uuid(),
                    "from": this.me,
                    "to": this.peer
                }
            }));
         if(pc!= null){
         	this.closePeerConnection(pc);         	
         }
    };
    skyrtc.prototype.sendConnect = function () {
       
                
                 this.socket.send(JSON.stringify({
                "eventName": "__connected",
                "data": {
                    "sessionId": this.sessionId,
		    						"sessionType": "IE",
                    "messageId": this.uuid(),
                    "from": this.me,
                    "to": this.peer
                }
            }));
    };
    //发送answer类型信令
    skyrtc.prototype.sendAnswer = function (socketId, sdp) {
        var pc = this.peerConnections[socketId];
        var that = this;
        pc.setRemoteDescription(new nativeRTCSessionDescription(sdp));
        pc.createAnswer(function (session_desc) {
            pc.setLocalDescription(session_desc);
            that.socket.send(JSON.stringify({
                "eventName": "__answer",
                "data": {
                    "socketId": socketId,
                    "sdp": session_desc.sdp
                }
            }));
        }, function (error) {
            console.log(error);
        });
    };

    //接收到answer类型信令后将对方的session描述写入PeerConnection中
    skyrtc.prototype.receiveAnswer = function (socketId, sdp) {
        var answersdk = {type:"answer", sdp:sdp};
       // console.log("receiveAnswer ----",answersdk);
        var pc = this.peerConnections[socketId];
        if(pc!= null){
          pc.setRemoteDescription(new nativeRTCSessionDescription(answersdk));	
        }
        
    };


    /***********************点对点连接部分*****************************/


    //创建与其他用户连接的PeerConnections
    skyrtc.prototype.createPeerConnections = function () {
        var i, m;
        for (i = 0, m = this.connections.length; i < m; i++) {
            this.createPeerConnection(this.connections[i]);
        }
    };

    //创建单个PeerConnection
    skyrtc.prototype.createPeerConnection = function (socketId) {
        var that = this;
        console.log("createPeerConnection start");
        var pc = new PeerConnection(iceServer);
        this.peerConnections[socketId] = pc;
        if(this.connectmode==="play"){
           this.dataChannels[socketId] = this.createDataChannel(socketId,"datachannel");
        }
        pc.onicegatheringstatechange = function (evt) {
           console.log("onicegatheringstatechange   ------------------------- ", pc.iceGatheringState);
           var sd = pc.currentRemoteDescription;
           if(sd){
           	 //console.log("Local session: type=    ", sd.type," sdp description=",sd.sdp);
           }
           var remotesd = pc.remoteDescription;
            if(remotesd){
           	// console.log("Local remote session: type=    ", remotesd.type," sdp remote description=",remotesd.sdp);
           }
           if(pc.iceGatheringState === "complete"){
           	 if (that.IceComplete === false) {
            		  that.IceComplete = true;
            	}           	
           }
        };
        pc.onicecandidate = function (evt) {
            console.log("pc_on_ice_candidate   ------------------------- ", evt.target.iceGatheringState);
            if (evt.candidate) {
                 console.log("onicecandidate ", evt.candidate.candidate);
                 that.socket.send(JSON.stringify({
                    "eventName": "__ice_candidate",
                    "data": {
                        "sessionId": that.sessionId,
                        "sessionType": "IE",
                        "messageId": that.uuid(),
                        "to": that.peer,
                        "from": that.me,
                        "label": evt.candidate.sdpMLineIndex,
                        "candidate": evt.candidate.candidate
                    }
                }));
                that.emit("pc_get_ice_candidate", evt.candidate, socketId, pc);
            }else{

            }

        };
        pc.onopen = function() {
            console.log("onopen ------------------------------------");
            that.emit("pc_opened", socketId, pc);
        };

        pc.onaddstream = function(evt) {
            console.log("onaddstream ------------------------------------");
            that.remoteMediaStream = evt.stream;
           
            that.emit('pc_add_stream', evt.stream, socketId, pc);
        };
        pc.ondatachannel = function (evt) {
            that.addDataChannel(socketId, evt.channel);
            that.emit('pc_add_data_channel', evt.channel, socketId, pc);
        };

        pc.oniceconnectionstatechange = function(evt) {
        	 console.log("On  ice  connection  state  change");
            if(pc.iceConnectionState ==="disconnected"){
            	    console.log("oniceconnectionstatechange   ------------------------- disconnected");
                  that.sendDisconnect(socketId);
            }else if(pc.iceConnectionState ==="connected") {
            	   console.log("oniceconnectionstatechange   ------------------------- connected");
                 that.sendConnect();
                 that.emit("stream_connected", that);
  
            }
            else if(pc.iceConnectionState ==="checking"){           	
              console.log("oniceconnectionstatechange   ------------------------- checking  IceComplete  =  ",that.IceComplete);            	
            }else if(pc.iceConnectionState ==="complete"){
              console.log("oniceconnectionstatechange   ------------------------- complete  IceComplete = ",that.IceComplete); 
    
            	          	
            }else if(pc.iceConnectionState ==="completed"){
                  console.log("oniceconnectionstatechange   ------------------------- completed");
            }else if(pc.iceConnectionState ==="failed"){
                  console.log("oniceconnectionstatechange   ------------------------- failed");
            }else{
            	    console.log("oniceconnectionstatechange   -------------------------unknow   iceConnectionState =  ", pc.iceConnectionState);
            }
           
        };
        pc.onsignalingstatechange = function(evt) {
           // console.log("onsignalingstatechange   ------------------------- -----",evt);
            var state = pc.signalingState;
            if(state){
            	 console.log("onsignalingstatechange   ---------pc_signalingState---------------- -----",state);
            	 if(state === "stable"){
            	 	  
            	 	}
            }
        };


        return pc;
    };

    //关闭PeerConnection连接
    skyrtc.prototype.closePeerConnection = function (pc) {
        if (!pc) return;
        pc.close();
    };


    /***********************数据通道连接部分*****************************/


    //消息广播
    skyrtc.prototype.broadcast = function (message) {
        var socketId;
        for (socketId in this.dataChannels) {
            this.sendMessage(message, socketId);
        }
    };

    //发送消息方法
    skyrtc.prototype.sendMessage = function (message, socketId) {
        if (this.dataChannels[socketId].readyState.toLowerCase() === 'open') {
            this.dataChannels[socketId].send(JSON.stringify({
                type: "__msg",
                data: message
            }));
        }else{
        	  console.log("sendMessage   ------------------------- -----",this.dataChannels[socketId].readyState.toLowerCase());
        }
    };

    //对所有的PeerConnections创建Data channel
    skyrtc.prototype.addDataChannels = function () {
        var connection;
        for (connection in this.peerConnections) {
            this.createDataChannel(connection);
        }
    };

    //对某一个PeerConnection创建Data channel
    skyrtc.prototype.createDataChannel = function (socketId, label) {
        var pc, key, channel;
        pc = this.peerConnections[socketId];
        if(pc!= null){
        if (!socketId) {
            this.emit("data_channel_create_error", socketId, new Error("attempt to create data channel without socket id"));
        }

        if (!(pc instanceof PeerConnection)) {
            this.emit("data_channel_create_error", socketId, new Error("attempt to create data channel without peerConnection"));
        }
        try {
            channel = pc.createDataChannel(label);
        } catch (error) {
        	   console.log("data_channel_create_error  ",socketId);
            this.emit("data_channel_create_error", socketId, error);
        }

        return this.addDataChannel(socketId, channel);
        }else{
        	return null;	
        }
    };

    //为Data channel绑定相应的事件回调函数
    skyrtc.prototype.addDataChannel = function (socketId, channel) {
        var that = this;
        channel.onopen = function () {
        	   console.log("data_channel_opened  ",socketId);
            that.emit('data_channel_opened', channel, socketId);
        };

        channel.onclose = function (event) {
        	  console.log("data_channel_closed  ");
            delete that.dataChannels[socketId];
            that.emit('data_channel_closed', channel, socketId);
        };

        channel.onmessage = function (message) {
        	  console.log("data_channel_message  ",message);
            var json;
            json = JSON.parse(message.data);
            if (json.type === '__file') {
                /*that.receiveFileChunk(json);*/
               // that.parseFilePacket(json, socketId);
            }else if (json.type === '__msg') {
            	  that.emit('player_message', channel, socketId, json.data);
            } else {
                that.emit('data_channel_message', channel, socketId, json.data);
            }
        };

        channel.onerror = function (err) {
        	  console.log("data_channel_error  ",err);
            that.emit('data_channel_error', channel, socketId, err);
        };

        this.dataChannels[socketId] = channel;
        return channel;
    };


    /**********************************************************/
    /*                                                        */
    /*                       文件传输                         */
    /*                                                        */
    /**********************************************************/

    /************************公有部分************************/

    //解析Data channel上的文件类型包,来确定信令类型
    skyrtc.prototype.parseFilePacket = function (json, socketId) {
        var signal = json.signal,
            that = this;
        if (signal === 'ask') {
            that.receiveFileAsk(json.sendId, json.name, json.size, socketId);
        } else if (signal === 'accept') {
            that.receiveFileAccept(json.sendId, socketId);
        } else if (signal === 'refuse') {
            that.receiveFileRefuse(json.sendId, socketId);
        } else if (signal === 'chunk') {
            that.receiveFileChunk(json.data, json.sendId, socketId, json.last, json.percent);
        } else if (signal === 'close') {
            //TODO
        }
    };

    /***********************发送者部分***********************/


    //通过Dtata channel向房间内所有其他用户广播文件
    skyrtc.prototype.shareFile = function (dom) {
        var socketId,
            that = this;
        for (socketId in that.dataChannels) {
            that.sendFile(dom, socketId);
        }
    };

    //向某一单个用户发送文件
    skyrtc.prototype.sendFile = function (dom, socketId) {
        var that = this,
            file,
            reader,
            fileToSend,
            sendId;
        if (typeof dom === 'string') {
            dom = document.getElementById(dom);
        }
        if (!dom) {
            that.emit("send_file_error", new Error("Can not find dom while sending file"), socketId);
            return;
        }
        if (!dom.files || !dom.files[0]) {
            that.emit("send_file_error", new Error("No file need to be sended"), socketId);
            return;
        }
        file = dom.files[0];
        that.fileChannels[socketId] = that.fileChannels[socketId] || {};
        sendId = that.getRandomString();
        fileToSend = {
            file: file,
            state: "ask"
        };
        that.fileChannels[socketId][sendId] = fileToSend;
        that.sendAsk(socketId, sendId, fileToSend);
        that.emit("send_file", sendId, socketId, file);
    };

    //发送多个文件的碎片
    skyrtc.prototype.sendFileChunks = function () {
        var socketId,
            sendId,
            that = this,
            nextTick = false;
        for (socketId in that.fileChannels) {
            for (sendId in that.fileChannels[socketId]) {
                if (that.fileChannels[socketId][sendId].state === "send") {
                    nextTick = true;
                    that.sendFileChunk(socketId, sendId);
                }
            }
        }
        if (nextTick) {
            setTimeout(function () {
                that.sendFileChunks();
            }, 10);
        }
    };

    //发送某个文件的碎片
    skyrtc.prototype.sendFileChunk = function (socketId, sendId) {
        var that = this,
            fileToSend = that.fileChannels[socketId][sendId],
            packet = {
                type: "__file",
                signal: "chunk",
                sendId: sendId
            },
            channel;

        fileToSend.sendedPackets++;
        fileToSend.packetsToSend--;


        if (fileToSend.fileData.length > packetSize) {
            packet.last = false;
            packet.data = fileToSend.fileData.slice(0, packetSize);
            packet.percent = fileToSend.sendedPackets / fileToSend.allPackets * 100;
            that.emit("send_file_chunk", sendId, socketId, fileToSend.sendedPackets / fileToSend.allPackets * 100, fileToSend.file);
        } else {
            packet.data = fileToSend.fileData;
            packet.last = true;
            fileToSend.state = "end";
            that.emit("sended_file", sendId, socketId, fileToSend.file);
            that.cleanSendFile(sendId, socketId);
        }

        channel = that.dataChannels[socketId];

        if (!channel) {
            that.emit("send_file_error", new Error("Channel has been destoried"), socketId, sendId, fileToSend.file);
            return;
        }
        channel.send(JSON.stringify(packet));
        fileToSend.fileData = fileToSend.fileData.slice(packet.data.length);
    };

    //发送文件请求后若对方同意接受,开始传输
    skyrtc.prototype.receiveFileAccept = function (sendId, socketId) {
        var that = this,
            fileToSend,
            reader,
            initSending = function (event, text) {
                fileToSend.state = "send";
                fileToSend.fileData = event.target.result;
                fileToSend.sendedPackets = 0;
                fileToSend.packetsToSend = fileToSend.allPackets = parseInt(fileToSend.fileData.length / packetSize, 10);
                that.sendFileChunks();
            };
        fileToSend = that.fileChannels[socketId][sendId];
        reader = new window.FileReader(fileToSend.file);
        reader.readAsDataURL(fileToSend.file);
        reader.onload = initSending;
        that.emit("send_file_accepted", sendId, socketId, that.fileChannels[socketId][sendId].file);
    };

    //发送文件请求后若对方拒绝接受,清除掉本地的文件信息
    skyrtc.prototype.receiveFileRefuse = function (sendId, socketId) {
        var that = this;
        that.fileChannels[socketId][sendId].state = "refused";
        that.emit("send_file_refused", sendId, socketId, that.fileChannels[socketId][sendId].file);
        that.cleanSendFile(sendId, socketId);
    };

    //清除发送文件缓存
    skyrtc.prototype.cleanSendFile = function (sendId, socketId) {
        var that = this;
        delete that.fileChannels[socketId][sendId];
    };

    //发送文件请求
    skyrtc.prototype.sendAsk = function (socketId, sendId, fileToSend) {
        var that = this,
            channel = that.dataChannels[socketId],
            packet;
        if (!channel) {
            that.emit("send_file_error", new Error("Channel has been closed"), socketId, sendId, fileToSend.file);
        }
        packet = {
            name: fileToSend.file.name,
            size: fileToSend.file.size,
            sendId: sendId,
            type: "__file",
            signal: "ask"
        };
        channel.send(JSON.stringify(packet));
    };

    //获得随机字符串来生成文件发送ID
    skyrtc.prototype.getRandomString = function () {
        return (Math.random() * new Date().getTime()).toString(36).toUpperCase().replace(/\./g, '-');
    };

    /***********************接收者部分***********************/


    //接收到文件碎片
    skyrtc.prototype.receiveFileChunk = function (data, sendId, socketId, last, percent) {
        var that = this,
            fileInfo = that.receiveFiles[sendId];
        if (!fileInfo.data) {
            fileInfo.state = "receive";
            fileInfo.data = "";
        }
        fileInfo.data = fileInfo.data || "";
        fileInfo.data += data;
        if (last) {
            fileInfo.state = "end";
            that.getTransferedFile(sendId);
        } else {
            that.emit("receive_file_chunk", sendId, socketId, fileInfo.name, percent);
        }
    };

    //接收到所有文件碎片后将其组合成一个完整的文件并自动下载
    skyrtc.prototype.getTransferedFile = function (sendId) {
        var that = this,
            fileInfo = that.receiveFiles[sendId],
            hyperlink = document.createElement("a"),
            mouseEvent = new MouseEvent('click', {
                view: window,
                bubbles: true,
                cancelable: true
            });
        hyperlink.href = fileInfo.data;
        hyperlink.target = '_blank';
        hyperlink.download = fileInfo.name || dataURL;

        hyperlink.dispatchEvent(mouseEvent);
        (window.URL || window.webkitURL).revokeObjectURL(hyperlink.href);
        that.emit("receive_file", sendId, fileInfo.socketId, fileInfo.name);
        that.cleanReceiveFile(sendId);
    };

    //接收到发送文件请求后记录文件信息
    skyrtc.prototype.receiveFileAsk = function (sendId, fileName, fileSize, socketId) {
        var that = this;
        that.receiveFiles[sendId] = {
            socketId: socketId,
            state: "ask",
            name: fileName,
            size: fileSize
        };
        that.emit("receive_file_ask", sendId, socketId, fileName, fileSize);
    };

    //发送同意接收文件信令
    skyrtc.prototype.sendFileAccept = function (sendId) {
        var that = this,
            fileInfo = that.receiveFiles[sendId],
            channel = that.dataChannels[fileInfo.socketId],
            packet;
        if (!channel) {
            that.emit("receive_file_error", new Error("Channel has been destoried"), sendId, socketId);
        }
        packet = {
            type: "__file",
            signal: "accept",
            sendId: sendId
        };
        channel.send(JSON.stringify(packet));
    };

    //发送拒绝接受文件信令
    skyrtc.prototype.sendFileRefuse = function (sendId) {
        var that = this,
            fileInfo = that.receiveFiles[sendId],
            channel = that.dataChannels[fileInfo.socketId],
            packet;
        if (!channel) {
            that.emit("receive_file_error", new Error("Channel has been destoried"), sendId, socketId);
        }
        packet = {
            type: "__file",
            signal: "refuse",
            sendId: sendId
        };
        channel.send(JSON.stringify(packet));
        that.cleanReceiveFile(sendId);
    };

    //清除接受文件缓存
    skyrtc.prototype.cleanReceiveFile = function (sendId) {
        var that = this;
        delete that.receiveFiles[sendId];
    };

    return new skyrtc();
};
